package com.zhengqing.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zhengqing.common.base.exception.MyException;
import com.zhengqing.common.redis.constant.RedisConstant;
import com.zhengqing.common.redis.util.RedisUtil;
import com.zhengqing.system.model.dto.YoutubeGetMediaDto;
import com.zhengqing.system.model.vo.ResolveMediaInfoVo;
import com.zhengqing.system.service.YoutubeDownloadService;
import com.zhengqing.system.util.EmailUtil;
import com.zhengqing.system.util.HttpUtil;
import com.zhengqing.system.util.IpUtil;
import com.zhengqing.system.util.SnowFlakeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.joda.time.DateTime;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName YoutubeDownloadServiceImpl
 * @Description TODO
 * @Author Des1gn
 * @Version 1.0
 **/
@Service
@Slf4j
public class YoutubeDownloadServiceImpl implements YoutubeDownloadService {

    @Resource
    KafkaTemplate<String,String> kafkaTemplate;


//    private final static String SNAP_BASE_PATH = "/home/youtube/";
    private final static String YOUTUBE_MEDIA_URL = "https://www.youtube.com/youtubei/v1/player";

    private final static List<String> QUALITY_LABEL_LIST = new LinkedList<>();

    private final static SnowFlakeUtil idUtil = new SnowFlakeUtil(9,9);

    static {
//        File pathFile = new File(SNAP_BASE_PATH);
//        if (!pathFile.exists()){
//            pathFile.mkdir();
//        }
        //设置清晰度顺序
        QUALITY_LABEL_LIST.add("1080p");
        QUALITY_LABEL_LIST.add("720p");
        QUALITY_LABEL_LIST.add("1440p");
        QUALITY_LABEL_LIST.add("2160p");
        QUALITY_LABEL_LIST.add("480p");
    }

    @Override
    public void downloadProcess(YoutubeGetMediaDto dto) {
        if (StringUtils.isBlank(dto.getMediaUrl())){
            log.error("获取youtube视频链接为空");
            return;
        }
        //解析视频id
        String videoId = getVideoId(dto.getMediaUrl());
        if (StringUtils.isBlank(videoId)){
            log.error("获取videoId失败");
            return;
        }
        //获取媒体信息
        String mediaInfoString = getMediaInfo(videoId);
        //获取要下载的媒体url
        ResolveMediaInfoVo mediaInfoVo = resolveMediaInfo(mediaInfoString);
        if (ObjectUtil.isNull(mediaInfoVo) || StringUtils.isBlank(mediaInfoVo.getMediaDownloadUrl())){
            log.error("媒体信息解析媒体链接失败->{}",mediaInfoString);
            return;
        }
        //发送邮件
        try {
            String videoDownloadUrl = StringUtils.isBlank(mediaInfoVo.getMediaDownloadUrl())?Strings.EMPTY:mediaInfoVo.getMediaDownloadUrl();
            String audioDownloadUrl = StringUtils.isBlank(mediaInfoVo.getAudioDownloadUrl())?Strings.EMPTY:mediaInfoVo.getAudioDownloadUrl();
            String content = "<p><a href='"+videoDownloadUrl+"'>点击视频下载</a></p>"+
                             "<p><a href='"+audioDownloadUrl+"'>点击音频下载</a></p>";
            EmailUtil.sendHtmlEmail(dto.getEmail(),"youtube_video", content);
        }catch (Exception e){
            log.error("youtube 视频邮件发送失败->{}",JSONObject.toJSONString(mediaInfoVo),e);
        }
    }

    @Override
    public Boolean sendMqToEmail(YoutubeGetMediaDto dto, HttpServletRequest request) {
        String key = RedisConstant.CATALOG_YOUTUBE_KEY + dto.getEmail();
        if (RedisUtil.hasKey(key) && !dto.getEmail().equals(RedisConstant.IGNORE_EMAIL)){
            throw new MyException(20001,"相同邮箱地址一天只能获取一次");
        }
        if (StringUtils.isBlank(dto.getMediaUrl()) || !dto.getMediaUrl().contains("youtube")){
            throw new MyException(20001,"youtube 链接错误");
        }
        //记录数据
        Long toDayEndTime = getToDayEndTime();
        RedisUtil.setEx(key,"1",toDayEndTime, TimeUnit.MILLISECONDS);
        //发送队列
        kafkaTemplate.send("youtube-queue", JSONObject.toJSONString(dto));
        return true;
    }

    @Override
    public Boolean sendMqToEmailProcess(YoutubeGetMediaDto param) {
        String url = "http://192.168.0.222:889/mini/api/youtube/getToEmail?mediaUrl=PARAM1&email=PARAM2";
        url = url.replaceAll("PARAM1",param.getMediaUrl());
        url = url.replaceAll("PARAM2",param.getEmail());
        HttpRequest getRequest = cn.hutool.http.HttpUtil.createGet(url);
        getRequest.execute();
        return true;
    }

    private Long getToDayEndTime(){
        long end = DateTime.now().millisOfDay().withMaximumValue().getMillis();
        long now = DateTime.now().getMillis();
        return end - now;
    }

//    private String saveMediaFile(byte[] bytes){
//        String filePath = SNAP_BASE_PATH+idUtil.nextId()+".mp4";
//        FileOutputStream fileOutputStream = null;
//        try {
//            fileOutputStream = new FileOutputStream(filePath);
//            fileOutputStream.write(bytes);
//            fileOutputStream.flush();
//        }catch (IOException e) {
//            log.error("媒体文件本地保存失败->{}",filePath);
//        }finally {
//            if (fileOutputStream != null) {
//                try {
//                    fileOutputStream.close();
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            }
//        }
//        return filePath;
//    }

    private ResolveMediaInfoVo resolveMediaInfo(String mediaInfoString){
        ResolveMediaInfoVo result = new ResolveMediaInfoVo();
        JSONObject mediaInfo = JSONObject.parseObject(mediaInfoString);
        JSONArray formats = mediaInfo.getJSONObject("streamingData").getJSONArray("adaptiveFormats");
        //获取视频链接
        for (String quality : QUALITY_LABEL_LIST) {
            if (StringUtils.isBlank(result.getMediaDownloadUrl())) {
                for (Object format : formats) {
                    JSONObject formatObject = JSONObject.parseObject(JSONObject.toJSONString(format));
                    if (!formatObject.getString("mimeType").startsWith("video")) {
                        continue;
                    }
                    if (!formatObject.containsKey("qualityLabel") || !formatObject.getString("qualityLabel").startsWith(quality)) {
                        continue;
                    }
                    if (!formatObject.containsKey("url")) {
                        continue;
                    }
                    result.setMediaDownloadUrl(formatObject.getString("url"));
                    break;
                }
            }
        }
        //获取音频链接
        for (Object format : formats) {
            JSONObject formatObject = JSONObject.parseObject(JSONObject.toJSONString(format));
            if (!formatObject.getString("mimeType").startsWith("audio")){
                continue;
            }
            if (!formatObject.containsKey("url")){
                continue;
            }
            result.setAudioDownloadUrl(formatObject.getString("url"));
            break;
        }
        return result;
    }

    private String getMediaInfo(String videoId){
       /* {
            "videoId": "eDxBGc9TD4c",
            "context": {
                "client": {
                    "clientName": "ANDROID_TESTSUITE",
                    "clientVersion": "1.9",
                    "androidSdkVersion": 30,
                    "hl": "en",
                    "gl": "US",
                    "utcOffsetMinutes": 0
                }
            }
        }*/
        JSONObject client = new JSONObject();
        client.put("clientName","ANDROID_TESTSUITE");
        client.put("clientVersion","1.9");
        client.put("androidSdkVersion","30");
        client.put("hl","en");
        client.put("gl","US");
        client.put("utcOffsetMinutes",0);

        JSONObject context = new JSONObject();
        context.put("client",client);

        JSONObject param = new JSONObject();
        param.put("videoId",videoId);
        param.put("context",context);
        String paramString = param.toJSONString();
        String responseString = null;
        try {
           responseString = HttpUtil.postOkHttp(YOUTUBE_MEDIA_URL, paramString);
        }catch (Exception e){
            log.error("获取媒体信息失败->{}",e);
        }
        if (StringUtils.isBlank(responseString)){
            log.error("获取媒体信息失败");
        }
        return responseString;
    }

    private String getVideoId(String url){
        int startIndex = url.indexOf("=");
        if (startIndex < 0){
            return null;
        }
        startIndex ++;
        int lastIndex = -1;
        if ((lastIndex = url.indexOf("&")) > -1){
        }else {
            lastIndex = url.length();
        }
        return url.substring(startIndex,lastIndex);
    }


}
